package compress;

import com.google.common.base.Preconditions;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class CompressDemo {
    static Logger logger = LoggerFactory.getLogger(CompressDemo.class);

    public static void main(String[] args) throws Exception {
        File srcFile = new File("D:\\tmp\\tests");
        File dstFile = new File("D:\\tmp\\test.zip");
        zipFile(srcFile, dstFile);
    }

    public static void zipFile(File srcFile, File dstFile) {
        Preconditions.checkArgument(srcFile != null, "srcFile is null.");
        Preconditions.checkArgument(dstFile != null, "dstFile is null.");
        logger.info("[source file] {}", srcFile, dstFile);
        logger.info("[dest   file] {}", srcFile, dstFile);
        ZipOutputStream zipOutputStream = null;
        try {
            zipOutputStream = new ZipOutputStream(new FileOutputStream(dstFile));
            zipFile(srcFile, zipOutputStream, "");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (zipOutputStream != null) {
                    zipOutputStream.close();
                }
            } catch (IOException e) {
                logger.error("IO有错误", e);
            }
        }
    }

    private static void zipFile(File srcFile, ZipOutputStream zipOutputStream, String baseDirectory) {
        Preconditions.checkArgument(srcFile != null);
        Preconditions.checkArgument(zipOutputStream != null);
        if (srcFile.isDirectory()) {
            File[] files = srcFile.listFiles();
            for (File file : files) {
                if (file.isDirectory()) {
                    zipFile(file, zipOutputStream, baseDirectory + file.getName() + File.separator);
                } else {
                    zipFile(file, zipOutputStream, baseDirectory);
                }
            }
        } else {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(srcFile);
                zipOutputStream.putNextEntry(new ZipEntry(baseDirectory + srcFile.getName()));
                byte[] buf = new byte[1024];
                while (inputStream.read(buf) != -1) {
                    zipOutputStream.write(buf);
                }
            } catch (FileNotFoundException e) {
                logger.error("文件不存在", e);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private static void zipDirectory(File baseDirectory, File srcDirectory, ZipOutputStream zipOutputStream) {
        Preconditions.checkArgument(srcDirectory != null);
        Preconditions.checkArgument(zipOutputStream != null);
        File[] files = srcDirectory.listFiles();
        int temp;
        for (File file : files != null ? files : new File[0]) {
            if (file.isDirectory()) {
                zipDirectory(baseDirectory, file, zipOutputStream);
            } else {
                FileInputStream inputStream = null;
                try {
                    inputStream = new FileInputStream(file);
                    zipOutputStream.putNextEntry(new ZipEntry(baseDirectory + File.separator + srcDirectory.getName()));
                    while ((temp = inputStream.read()) != -1) {
                        zipOutputStream.write(temp);
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
